(function ($) {
    $.fn.yqUJsonEdit = function (opts, param) {
        if (typeof opts == 'string') {
            return $.fn.yqUJsonEdit.methods[opts](this, param);
        }

        return this.each(function () {
            var $this = $(this);
            var opt;
            if ($this.data("yqtype") == "yqUJsonEdit") {
                // var $uniqueID = $this.attr("ID");
                // var opts_ = $.extend({}, options($this));
                // destroy($this);
                // $this = $("#" + $uniqueID);
                // opt = $.extend(opts_, opts);
            } else {
                opt = $.extend({}, $.fn.yqUJsonEdit.defaults, opts);
                // var $uniqueID = $this.attr("ID");
                // if ($uniqueID === undefined || $uniqueID === null || $uniqueID == "") {
                //     $uniqueID = $.getUniqueID();
                //     $this.attr("ID", $uniqueID);
                // }
            }

            if (opt.width === undefined && $this.width() > 0) {
                opt.width = $this.width();
            }
            else if (typeof opt.width != "undefined") {
                $this.width(opt.width);
            }

            if (opt.height === undefined && $this.height() > 0) {
                opt.height = $this.height();
            }
            else if (typeof opt.height != "undefined") {
                $this.height(opt.height);
            }

            //组件加载结束
            opt.onload = true;
            //组件进程执行中
            opt.running = false;

            //变量信息
            $this.data("yqujsonedit_opt", opt);
            $this.data("yqtype", "yqUJsonEdit");

            var file = [];
            file.push({ url: "/scripts/crypto/sha256.min.js", type: "js" });
            $.yqLoadJsCss(file, function () {
                init_ui($this);
            })

            return $this;
        });
    };

    $.fn.yqUJsonEdit.defaults = {
        theme: "eclipse",
        fontSize: 14,
        data: {},
        goDocEnd: false,
        afterBindingTitle: function () { }, //标题绑定后
    };

    $.fn.yqUJsonEdit.methods = {
        options: function (jq) {
            return options($(jq));
        },
        resize: function (jq, params) {
            resize($(jq), params)
        }, destroy: function (jq) {
            destroy($(jq[0]));
        },
    };

    function options($object) {
        return $object.data("yqujsonedit_opt");
    }

    function resize($object, params) {
        var opt = options($object);
        if (typeof params == "object") {
            opt.width = params.width;
            opt.height = params.height;
        }
        opt.$title.css({ "border-spacing": 0, scrolling: "no", height: 34, width: opt.width });
        opt.$edit.yqCodeEdit("resize", { width: opt.width, height: opt.height - 34 });
    }

    function destroy($object) {
        var opt = options($object);
        opt.$edit.yqCodeEdit("destroy");
        opt.$edit.remove();

        opt.$title.find(".theme").combobox("destroy");
        opt.$title.find(".font").combobox("destroy");
        // opt.$title.find(".search").linkbutton( 
        // opt.$title.find(".edit").linkbutton( 
        // opt.$title.find(".jsonedit").switchbutton( 
        // opt.$title.find(".save").linkbutton( 
        // opt.$title.find(".reload").linkbutton( 
        // opt.$title.find(".download").linkbutton({
        opt.$title.remove();
    }

    function init_ui($object) {
        var opt = options($object);

        $object.width(opt.width);
        $object.height(opt.height - 34);

        var $title = $(`
    <table >
        <tr>
          <td align="left" style="padding: 0 0 0 2px;white-space: nowrap;"></td>
          <td align="right" style="padding: 0 2px 0 0;white-space: nowrap;"> 
                <input class="theme"/>
                <input class="font"/>   
                <a class="mask" title="mask edit"></a>
                <a class="edit" title="data edit"></a>
                <input class="jsonedit" title="json edit"/>
                <a class="save" title="save"></a>
                <a class="reload" title="reload"></a>
                <a class="download" title="download"></a>
          </td>
        </tr>
    </table>`);
        opt.$title = $title;

        $title.css({ "border-spacing": 0, scrolling: "no", height: 34, width: opt.width });
        $object.before($title);
        $($title.find("td")[0]).html('<lable class="name">' + opt.data.name + '</lable><lable class="size">' + formatSize(opt.data.size, 2)) + '</lable>';

        var themes_ = [];
        var themes = $.fn.yqCodeEdit.defaults.themes
        for (let i = 0; i < themes.length; i++) {
            const item = themes[i];
            themes_.push({
                "id": item,
                "text": item
            });
        }
        $title.find(".theme").combobox({
            width: 150,
            label: "theme",
            labelWidth: 55,
            data: themes_,
            valueField: "id",
            textField: "text",
            value: opt.edit_theme === undefined ? "eclipse" : opt.edit_theme,
            onChange: function (newValue, oldValue) {
                opt.edit_theme = newValue;
                opt.$edit.yqCodeEdit("setTheme", newValue);
            }
        });
        //兼容错误字体居右
        $title.find(".theme").next().css({ "text-align": "left" });

        $title.find(".font").combobox({
            width: 140,
            label: "font-size",
            labelWidth: 72,
            data: [{
                "id": 12,
                "text": "12px"
            }, {
                "id": 14,
                "text": "14px"
            }, {
                "id": 16,
                "text": "16px"
            }, {
                "id": 18,
                "text": "18px"
            }, {
                "id": 20,
                "text": "20px"
            }, {
                "id": 24,
                "text": "24px"
            }, {
                "id": 28,
                "text": "28px"
            }, {
                "id": 32,
                "text": "32px"
            }],
            valueField: "id",
            textField: "text",
            value: opt.edit_font_size === undefined ? 14 : opt.edit_font_size,
            onChange: function (newValue, oldValue) {
                opt.edit_font_size = newValue;
                opt.$edit.yqCodeEdit("setFontSize", newValue);
            }
        });
        $title.find(".font").next().css({ "text-align": "left" });

        $title.find(".mask").linkbutton({
            iconCls: 'icon2-mask',
            plain: false,
            disabled: false,
            onClick: function () {
                var value = JSON.parse(opt.$edit.yqCodeEdit("getValue"));
                var ui_type = value.ui_mask.ui_type;
                var param = value.ui_mask.param;
                delete value.ui_mask.ui_type;
                delete value.ui_mask.param;
                var w_ = $(window).width();
                var w__ = w_ < -900 ? w_ : 900
                var show_pops = {
                    mdiinfo: $.yqGetWindParams(),
                    width: w__,
                    height: $(window).height(),
                    horizontalAlign: "right",
                    ui_type: ui_type,
                    ui_mask: value.ui_mask,
                    param: param,
                    isEdit: true,
                    callback: function (data) {
                        value.ui_mask = data;
                        opt.$edit.yqCodeEdit("setValue", $.jsonFormat(value));
                        $title.find(".save").linkbutton("enable");
                    }
                };

                if (window.top == window.self) {
                    $.yqVirtualPopEdit(show_pops);
                }
                else {
                    window.top.$.yqVirtualPopEdit(show_pops);
                }
            }
        });

        $title.find(".edit").linkbutton({
            iconCls: 'icon2-edit',
            plain: false,
            disabled: false,
            onClick: function () {
                var value = JSON.parse(opt.$edit.yqCodeEdit("getValue"));
                var w_ = $(window).width();
                var w__ = w_ < -700 ? w_ : 700
                var show_pops = {
                    mdiinfo: $.yqGetWindParams(),
                    width: w__,
                    height: $(window).height(),
                    horizontalAlign: "right",

                    ui_mask: value.ui_mask,  //数据列配置对象
                    data: value.data,

                    isEdit: true,
                    callback: function (data) {
                        value.data = data;
                        opt.$edit.yqCodeEdit("setValue", $.jsonFormat(value));
                        $title.find(".save").linkbutton("enable");
                    }
                };

                if (window.top == window.self) {
                    $.yqUnitPopEdit(show_pops);
                }
                else {
                    var w_ = $(window.top).width();
                    var w__ = w_ < -700 ? w_ : 700;
                    show_pops.width = w__;
                    show_pops.height = $(window.top).height();
                    window.top.$.yqUnitPopEdit(show_pops);
                }
            }
        });

        $title.find(".jsonedit").switchbutton({
            width: 60,
            checked: false,
            handleText: '<span class="fa fa-pencil-square-o" aria-hidden="true" style="padding: 7px;color: dodgerblue;"></span>',
            onText: 'on',
            offText: "off",
            onChange: function (checked) {
                if (checked) {
                    $title.find(".save").linkbutton("enable");
                    opt.$edit.yqCodeEdit("enable");
                } else {
                    $title.find(".save").linkbutton("disable");
                    opt.$edit.yqCodeEdit("disable");
                }
            }
        });

        $title.find(".save").linkbutton({
            iconCls: 'icon2-save',
            plain: false,
            disabled: true,
            onClick: function () {
                var value = opt.$edit.yqCodeEdit("getValue");
                filesave(opt.data, value, function (res) {
                    console.log("save", res);
                    if (res.error == 0) {
                        $title.find(".save").linkbutton("disable");
                        $title.find(".jsonedit").switchbutton("uncheck");
                        $($title.find("td")[0]).html('<lable class="name">' + res.data.name + '</lable><lable class="size">' + formatSize(res.data.size, 2)) + '</lable>';
                        $.messager.show({
                            title: 'success',
                            msg: '文件已保存。',
                            timeout: 3000,
                            showType: 'show'
                        });
                    } else {
                        $.messager.alert('fail', '文件已保存失败!', 'info');
                    }
                })
            }
        });

        $title.find(".reload").linkbutton({
            iconCls: 'icon2-reload',
            plain: false,
            onClick: function () {
                $title.find(".save").linkbutton("disable");
                fileget(opt.data.file, function (text) {
                    opt.$edit.yqCodeEdit("setValue", text);
                    $.messager.show({
                        title: 'success',
                        msg: '文件刷新成功。',
                        timeout: 3000,
                        showType: 'show'
                    });
                });
            }
        });

        $title.find(".download").linkbutton({
            iconCls: 'icon2-download',
            plain: false,
            onClick: function () {
                var data = opt.$edit.yqCodeEdit("getValue");
                let blob = new Blob([data]);
                let _url = URL.createObjectURL(blob);
                let a = document.createElement('a');
                a.setAttribute('download', opt.data.name);
                a.setAttribute('href', _url);
                a.click();
            }
        });

        opt.$edit = $(`<textarea></textarea>`);
        opt.$edit.css({ width: opt.width, height: opt.height - 34 });
        $title.after(opt.$edit);

        opt.$edit.yqCodeEdit({
            isEdit: false,
            theme: opt.theme,
            fontSize: opt.fontSize,
            type: "json",
            types: ["json"],
            goDocEnd: false,
            value: "",
        });

        fileget(opt.data.file, function (text) {
            opt.$edit.yqCodeEdit("setValue", text);
            opt.afterBindingTitle.call($object);
        })
    }

    /**
    * 格式化文件大小, 输出成带单位的字符串
    * @param {Number} size 文件大小
    * @param {Number} [pointLength=2] 精确到的小数点数。
    * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。
    *    如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.
    */
    function formatSize(size, pointLength) {
        if (pointLength === undefined) {
            pointLength = 0;
        }

        var unit;
        var units = ['B', 'K', 'M', 'G', 'TB'];
        while ((unit = units.shift()) && size > 1024) {
            size = size / 1024;
        }
        return (unit === 'B' ? size : size.toFixed(pointLength === undefined ? 2 : pointLength)) + unit;
    }

    //--文件操作 begin-----------------------------
    function fileget(fileid, callback) {
        var formData = new FormData();
        formData.append("action", "downfile");
        formData.append("file", fileid);
        $.ajax({
            type: 'POST',
            url: "_resource.html",
            data: formData,
            processData: false,
            contentType: false,
            dataType: "text",
            success: function (text) {
                callback(text);
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                console.log(XMLHttpRequest.responseText);
                callback(XMLHttpRequest.responseText);
            }
        });
    }

    function filesave(data, f_txt, callback) {
        const blob = new Blob([f_txt], { type: data.mine });
        // createObjectURL() 静态方法创建一个 DOMString，其中包含一个 URL，该 URL 表示参数中给定的对象。

        var fileFingerprint;
        var reader = new FileReader();
        reader.onload = function () {
            fileFingerprint = HashBase64(reader.result, 'SHA256');
            upload();
        }
        reader.readAsArrayBuffer(blob);

        function upload() {
            var formData = new FormData();
            formData.set('action', 'uploadfile');
            formData.set('file', blob);
            formData.set('name', data.file);
            formData.set('finger', fileFingerprint);
            $.ajax({
                type: 'post',
                url: "_resource.html",
                data: formData,
                cache: false,
                processData: false,
                contentType: false,
                dataType: 'json',
                success: function (res) {
                    callback(res);
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    console.error(errorThrown);
                    callback({ error: 99, info: errorThrown });
                }
            });
        }
    }

    function HashBase64(str, protocol = 'SHA256') {
        result = str
        switch (protocol) {
            case 'MD5':
                result = String.fromCharCode(...md5.array(str))
                break;
            case 'SHA1':
                result = String.fromCharCode(...sha1.array(str))
                break;
            case 'SHA224':
                result = String.fromCharCode(...sha224.array(str))
                break;
            case 'SHA256':
                result = String.fromCharCode(...sha256.array(str))
                break;
        }
        result = btoa(result).replaceAll("\/", "_").replaceAll("+", "-");
        return result;
    }
    //--文件操作 end-------------------------------

})(jQuery);
